#include <simulator/memory/memory.h>
#include <simulator/memory/segment.h>
#include <simulator/report/report.h>
#include <simulator/bitTools/bitTools.h>

void Memory::addSegment(const std::shared_ptr<Segment> &segment) {
    m_segments.push_back(segment);
}

std::shared_ptr<Segment> Memory::findSegmentByAddress(u64 address) {
    for (auto &segment: m_segments) {
        if (address < segment->getAddressBegin() + segment->getSegmentSize() &&
            address >= segment->getAddressBegin()) {
            return segment;
        }
    }
    return nullptr;
}

std::vector<u8> Memory::readNBytes(u64 address, u64 N) {
    std::vector<u8> data;
    std::shared_ptr<Segment> segment = findSegmentByAddress(address);

    // 如果当前地址不在任何段中，打印错误信息
    if (!segment) {
        std::string msg = "读内存失败！访问地址为:" + dec2hex(address);
        warningMacro(msg.c_str());
        return {};
    }

    // 段必须可读
    if (segment->canRead()) {
        data = segment->readNBytes(address - segment->getAddressBegin(), N);
    }
    return data;
}

void Memory::writeNBytes(const std::vector<u8> &data, u64 address, u64 N) {
    // 找到address所在的段
    std::shared_ptr<Segment> segment = findSegmentByAddress(address);
    // 如果当前地址不在任何段中，打印错误信息
    if (!segment) {
        std::string msg = "写内存失败！访问地址为:" + dec2hex(address);
        warningMacro(msg.c_str());
        return;
    }

    // 段必须可写
    if (segment->canWrite()) {
        segment->write(address - segment->getAddressBegin(), N, data);
    }
}

Memory::Memory(const Memory &memory) {
    for (auto &segment: memory.m_segments) {
        m_segments.emplace_back(std::make_shared<Segment>(*segment));
    }
}
